<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        
    </style>
</head>
<body>
    
</body>
<script>

    function Parent(m){
        this.msg = m
    }
    Parent.prototype.show = function(){
        console.log(this.msg);
    }

    const Child = CreateExtend( Parent, "hello" );
    const c = new Child();

    console.log(c);         // { msg: "hello" }
    console.log(c.msg);     // hello
    c.show()                // hello

    // 请封装并实现extend的功能

    function CreateExtend(){
        // 因为将来会出现其他函数，在其他函数内获取不到外部的arguments
        // 所以提前将接收到的外部的参数所在的arguments保存起来
        // 同时因为arguments是个伪数组，顺手转成真数组，方便操作
        const arg = [...arguments];
        // 因为第0个参数为父类，真正被作为参数是从第1个开始
        // 所以从第1个开始截取到最后一个
        const arr = arg.slice(1);
        // 准备子类
        function Child(){
            // 通过改变this指向继承父类内的属性并将参数覆盖过去
            arg[0].apply(this, arr);
        }
        // 准备继承父类的原型
        Child.prototype = new arg[0]();

        // 因为使用的是原型链继承：原型链继承，既会继承...又会继承...
        // 而我们已经使用改变this指向继承，继承了父类内的属性，所以将原型链继承时，继承到的父类自带的属性删掉
        // for(let i in Child.prototype){
        //     delete Child.prototype[i];
        // }
        // 给子类的原型添加来源标志
        // Child.prototype.constructor = Child;
        
        // 返回创建好继承关系的子类
        return Child;
    }


    // new的原理
        // 1. 创建新对象
        // 2. 。。。
        // 3. 。。。
        // 4. 。。。
        // 5. 如果没有主动返回对象，那么返回这个新对象



    class Abc extends Parent{
        constructor(m){
            super(m)
        }
    }
    const a = new Abc("abc")
    console.log(a)


    
</script>
</html>